package kitwee.com.kanpad.orderDetail;


import android.annotation.SuppressLint;
import android.content.Context;

import com.kitwee.serialport.SerialPortManager;
import com.kitwee.serialport.callback.SerialPortCallback;
import com.kitwee.serialport.instruction.Instruction;
import com.kitwee.serialport.data.model.SerialPortData;
import com.kitwee.serialport.data.model.SerialPortParam;
import com.kitwee.serialport.exception.SerialPortException;
import com.kitwee.serialport.instruction.PanasonicInstruction;

import com.blankj.utilcode.util.ToastUtils;

import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import kitwee.com.kanpad.BuildConfig;

public final class SerialPortHelper {

    private Context mAppContext;

    private static final Object mLock = new Object();

    @SuppressLint("StaticFieldLeak")
    private static SerialPortHelper mInstance;

    private SerialPortParam mParam;

    private Set<SerialPortCallback> mCallbacks = new HashSet<>();

    // 串口是否已打开
    private boolean mOpened = false;

    // 是否发送暂停指令
    private boolean mPaused = false;
    private String mPausedData; // 串口暂停时的零值数据

    private SerialPortHelper(Context context) {
        mAppContext = context.getApplicationContext();
    }

    public static SerialPortHelper getInstance(Context context) {
        synchronized (mLock) {
            if (mInstance == null) {
                mInstance = new SerialPortHelper(context.getApplicationContext());
            }
            return mInstance;
        }
    }

    /**
     * 打开串口；初始化上传服务
     */
    public void openSerialPort(SerialPortParam param) {
        if (param == null) {
            ToastUtils.showShort("注意！尚未配置串口参数！");
            return;
        }
        mParam = param;
        if (mOpened) {
            closeSerialPort();
        }
        openSerialPortReally();
        SerialPortReporter.getInstance().initialize(mAppContext);
    }

    /**
     * 打开串口
     */
    private void openSerialPortReally() {
        try {
            SerialPortManager.getInstance(mAppContext)
                    .setDebug(BuildConfig.DEBUG)
                    .testMode(false)
                    .setInstruction(getInstructionSet())
                    .setParam(mParam)
                    .setCallback(mInternalCallback)
                    .open();
            mOpened = true;

        } catch (SerialPortException e) {
            mOpened = false;
            ToastUtils.showShort(e.getMessage());
        }
    }

    /**
     * 改变暂停状态
     *
     * @param paused 是否已暂停
     */
    public void setPaused(boolean paused) {
        if (paused && mPausedData == null) {
            Map<String, String> data = new HashMap<>();
            for (Instruction ins : getInstructionSet()) {
                data.put(ins.getKey(), "0");
            }
            mPausedData = new JSONObject(data).toString();
        }
        if (mPaused != paused) {
            mPaused = paused;
            SerialPortReporter.getInstance().onPausedStatusChanged(paused);
            closeSerialPortReally();
            openSerialPortReally();
        }
    }

    /**
     * 串口数据回调
     */
    private SerialPortCallback mInternalCallback = new SerialPortCallback() {
        @Override
        public void onSuccess(SerialPortData data) {
            for (SerialPortCallback callback : mCallbacks) {
                if (callback != null) {
                    callback.onSuccess(data);
                }
            }
            if (mPaused) {
                data.setData(mPausedData);
            }
            SerialPortReporter.getInstance().reportRealTimeData(mPaused, data);
        }

        @Override
        public void onException(SerialPortException e) {

        }
    };

    /**
     * 从服务端拉取指令
     */
    private ArrayList<Instruction> getInstructionSet() {
        if (mPaused) {
            return new ArrayList<Instruction>() {{
                add(getPausedInstruction());
            }};
        }

        ArrayList<Instruction> instructions = new ArrayList<>();

        instructions.add(
                new PanasonicInstruction("DT32482", PanasonicInstruction.DT32482)
        );

        instructions.add(
                new PanasonicInstruction("DT32450", PanasonicInstruction.DT32450)
        );

        instructions.add(
                new PanasonicInstruction("DT32710", PanasonicInstruction.DT32710)
        );

        instructions.add(
                new PanasonicInstruction("DT32714", PanasonicInstruction.DT32714)
        );

        instructions.add(
                new PanasonicInstruction("DT32717", PanasonicInstruction.DT32717)
        );
        instructions.add(
                new PanasonicInstruction("DT32542", PanasonicInstruction.DT32542)
        );
        instructions.add(
                new PanasonicInstruction("DT32761", PanasonicInstruction.DT32761)
        );

        instructions.add(
                new PanasonicInstruction("DT214", PanasonicInstruction.DT214)
        );
        instructions.add(
                new PanasonicInstruction("DT32763", PanasonicInstruction.DT32763)
        );

        instructions.add(
                new PanasonicInstruction("DT32745", PanasonicInstruction.DT32745)
        );

//        展厅的
//
//        instructions.add(
//                new Instruction("DT32712", Bytes.bytes2HexString(PanasonicInstruction.DT32712))
//        );
//
//        instructions.add(
//                new Instruction("DT32720", Bytes.bytes2HexString(PanasonicInstruction.DT32720))
//        );


        return instructions;
    }

    /**
     * 获取暂停指令
     */
    private Instruction getPausedInstruction() {
        return new PanasonicInstruction("R00", PanasonicInstruction.R00);
    }

    /**
     * 添加回调
     *
     * @param callback 回调
     */
    public void addCallback(SerialPortCallback callback) {
        mCallbacks.add(callback);
    }

    /**
     * 移除回调
     */
    public void removeCallback(SerialPortCallback callback) {
        if (mCallbacks.contains(callback)) {
            mCallbacks.remove(callback);
        }
    }

    /**
     * 关闭串口；反初始化上传服务
     */
    public void closeSerialPort() {
        if (mOpened) {
            closeSerialPortReally();
            SerialPortReporter.getInstance().deinitialize();
        }
    }

    /**
     * 关闭串口
     */
    private void closeSerialPortReally() {
        SerialPortManager.getInstance(mAppContext)
                .removeCallback().close();
        mOpened = false;
    }


}
